/*
 * Copyright � 2008 Nokia Corporation.
 */

#include "SudokuBtnControl.h"
#include "SudokuAppView.h"
#include "SudokuGridControl.h"
#include "SudokuGameLogic.h"
#include "SudokuAppUi.h"

#include <fbs.h>
#include <eikenv.h>

CSudokuBtnControl::CSudokuBtnControl (CSudokuContainerControl& aParent, CFbsBitGc*& aBgc)
:iBgc(aBgc),iParent(aParent)
    {
    // No implementation required
    }

CSudokuBtnControl::~CSudokuBtnControl ()
    {
    }

CSudokuBtnControl* CSudokuBtnControl::NewLC (CSudokuContainerControl& aParent, const TRect& aRect,CFbsBitGc*& aBgc)
    {
    CSudokuBtnControl* self = new (ELeave)CSudokuBtnControl(aParent, aBgc);
    CleanupStack::PushL (self );
    self->ConstructL (aRect);
    return self;
    }

CSudokuBtnControl* CSudokuBtnControl::NewL (CSudokuContainerControl& aParent, const TRect& aRect,CFbsBitGc*& aBgc)
    {
    CSudokuBtnControl* self=CSudokuBtnControl::NewLC (aParent, aRect, aBgc);
    CleanupStack::Pop ( ); // self;
    return self;
    }

void CSudokuBtnControl::ConstructL (const TRect& /*aRect*/)
    {
    SetContainerWindowL(iParent);
    }


void CSudokuBtnControl::Draw( const TRect& /*aRect*/ ) const
    {
    // Remember to draw into backbuffer iBgc
    DrawBtns();
    }

void CSudokuBtnControl::DrawBtns() const
    {
    iParent.UseFont(iParent.GridFont());

    TRgb customBlack = KRgbBlack;
    customBlack.SetAlpha(90);
    iBgc->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBgc->SetBrushColor(customBlack);
    iBgc->DrawRect(Rect());
  
    
    // Draw buttons
    iBgc->SetPenColor(KRgbWhite);
    
    TInt txtWidth = iParent.GridFont()->TextWidthInPixels(_L("8"));
    TInt txtHeight = iParent.GridFont()->HeightInPixels();

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn1Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn1Rect, TSize(4,4));
    TPoint textPoint = iBtn1Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn1Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("1"),textPoint);
    
    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn2Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn2Rect, TSize(4,4));
    textPoint = iBtn2Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn2Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("2"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn3Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn3Rect, TSize(4,4));
    textPoint = iBtn3Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn3Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("3"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn4Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn4Rect, TSize(4,4));
    textPoint = iBtn4Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn4Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("4"),textPoint);
    
    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn5Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn5Rect, TSize(4,4));
    textPoint = iBtn5Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn5Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("5"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn6Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn6Rect, TSize(4,4));
    textPoint = iBtn6Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn6Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("6"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn7Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn7Rect, TSize(4,4));
    textPoint = iBtn7Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn7Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("7"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn8Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn8Rect, TSize(4,4));
    textPoint = iBtn8Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn8Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("8"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtn9Rect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtn9Rect, TSize(4,4));
    textPoint = iBtn9Rect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtn9Rect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("9"),textPoint);

    iBgc->SetBrushColor(KRgbBlack);
    if (iBtnCRect.Contains(iDragPoint))
        {
        iBgc->SetBrushColor(KRgbGray);
        }
    iBgc->DrawRoundRect(iBtnCRect, TSize(4,4));
    textPoint = iBtnCRect.iTl;
    textPoint.iY += txtHeight;
    textPoint.iX += (iBtnCRect.Width() - txtWidth) / 2;
    iBgc->DrawText(_L("C"),textPoint);

    iBgc->SetBrushStyle(CGraphicsContext::ENullBrush);
    }

void CSudokuBtnControl::SizeChanged()
    {
    // Set buttons rect

    // Calculate one button rect
    TInt width = Rect().Size().iWidth;
    TInt height = Rect().Size().iHeight;
    TSize btnSize = TSize(width/4, height/4);
    TPoint tl = Rect().iTl;
    TInt x = tl.iX + ((width-btnSize.iWidth*3)/2);
    TPoint btnTl = TPoint(x,tl.iY); 
    TRect btnRect = TRect(TPoint(x,tl.iY),btnSize);

    TRect tmp = btnRect;
    
    // First row 1,2,3 buttons
    iBtn1Rect = btnRect;
    btnRect.Move(btnSize.iWidth,0);
    iBtn2Rect = btnRect;
    btnRect.Move(btnSize.iWidth,0);
    iBtn3Rect = btnRect;

    // Second row 4,5,6 buttons
    btnRect = tmp;
    btnRect.Move(0,btnSize.iHeight);
    iBtn4Rect = btnRect;
    btnRect.Move(btnSize.iWidth,0);
    iBtn5Rect = btnRect;
    btnRect.Move(btnSize.iWidth,0);
    iBtn6Rect = btnRect;
    
    // Third row 7,8,9 buttons
    btnRect = tmp;
    btnRect.Move(0,btnSize.iHeight*2);
    iBtn7Rect = btnRect;
    btnRect.Move(btnSize.iWidth,0);
    iBtn8Rect = btnRect;
    btnRect.Move(btnSize.iWidth,0);
    iBtn9Rect = btnRect;
    
    // Fourth row, the one C button
    btnRect = tmp;
    btnRect.Move(0,btnSize.iHeight*3);
    btnRect.Move(btnSize.iWidth,0);
    iBtnCRect = btnRect;
    
    // Default btn
    iDragPoint = iBtn5Rect.Center();
    }

TKeyResponse CSudokuBtnControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    TKeyResponse ret = EKeyWasNotConsumed;
    TInt number = KErrNotFound;
    
    if (aType == EEventKeyDown)
        {
        TInt gridItemWidth = iBtn5Rect.Width();
        TInt gridItemHeight = iBtn5Rect.Height();
        TPoint tmpPoint = iDragPoint;

        switch (aKeyEvent.iScanCode)
            {
            case '1':
                {
                number = 1;
                ret = EKeyWasConsumed;
                break;
                }
            case '2':
                {
                number = 2;
                ret = EKeyWasConsumed;
                break;
                }
            case '3':
                {
                number = 3;
                ret = EKeyWasConsumed;
                break;
                }
            case '4':
                {
                number = 4;
                ret = EKeyWasConsumed;
                break;
                }
            case '5':
                {
                number = 5;
                ret = EKeyWasConsumed;
                break;
                }
            case '6':
                {
                number = 6;
                ret = EKeyWasConsumed;
                break;
                }
            case '7':
                {
                number = 7;
                ret = EKeyWasConsumed;
                break;
                }
            case '8':
                {
                number = 8;
                ret = EKeyWasConsumed;
                break;
                }
            case '9':
                {
                number = 9;
                ret = EKeyWasConsumed;
                break;
                }
            case EStdKeyBackspace:
                {
                number = 0;
                ret = EKeyWasConsumed;
                break;
                }
            case EStdKeyUpArrow:
                {
                tmpPoint.iY -= gridItemHeight;
                TInt ret = Number(tmpPoint);
                if (ret!=KErrNotFound)
                    {
                    iDragPoint = tmpPoint;
                    ret = EKeyWasConsumed;
                    }
                break;
                }
            case EStdKeyDownArrow:
                {
                tmpPoint.iY += gridItemHeight;
                TInt ret = Number(tmpPoint);
                if (ret!=KErrNotFound)
                    {
                    iDragPoint = tmpPoint;
                    ret = EKeyWasConsumed;
                    }
                break;
                }
            case EStdKeyLeftArrow:
                {
                tmpPoint.iX -= gridItemWidth;
                TInt ret = Number(tmpPoint);
                if (ret!=KErrNotFound)
                    {
                    iDragPoint = tmpPoint;
                    ret = EKeyWasConsumed;
                    }
                break;
                }
            case EStdKeyRightArrow:
                {
                tmpPoint.iX += gridItemWidth;
                TInt ret = Number(tmpPoint);
                if (ret!=KErrNotFound)
                    {
                    iDragPoint = tmpPoint;
                    ret = EKeyWasConsumed;
                    }
                break;
                }
            case EStdKeyDevice3: // Center key
            case EStdKeyDevice0: // Select key
                {
                number = Number(iDragPoint);
                ret = EKeyWasConsumed;
                break;
                }                
            default:
                {
                break;
                }
            };
        }
    
    if (number != KErrNotFound)
        {
        MakeVisible(EFalse);
        iDragPoint = iBtn5Rect.Center();
        iParent.GridControl()->NumberBtnPressed(number);
        }
    
    return ret;
    }

void CSudokuBtnControl::HitActiveNumber()
    {
    TInt number = Number(iDragPoint);
    MakeVisible(EFalse);
    iDragPoint = iBtn5Rect.Center();
    iParent.GridControl()->NumberBtnPressed(number);
    }

TInt CSudokuBtnControl::Number(TPoint aPoint)
    {
    TInt number = KErrNotFound;
    if (iBtn1Rect.Contains(aPoint))
        {
        number = 1;
        }
    else if (iBtn1Rect.Contains(aPoint))
        {
        number = 1;
        }
    else if (iBtn2Rect.Contains(aPoint))
        {
        number = 2;
        }
    else if (iBtn3Rect.Contains(aPoint))
        {
        number = 3;
        }
    else if (iBtn4Rect.Contains(aPoint))
        {
        number = 4;
        }
    else if (iBtn5Rect.Contains(aPoint))
        {
        number = 5;
        }
    else if (iBtn6Rect.Contains(aPoint))
        {
        number = 6;
        }
    else if (iBtn7Rect.Contains(aPoint))
        {
        number = 7;
        }
    else if (iBtn8Rect.Contains(aPoint))
        {
        number = 8;
        }
    else if (iBtn9Rect.Contains(aPoint))
        {
        number = 9;
        }
    else if (iBtnCRect.Contains(aPoint))
        {
        number = 0;
        }
    return number;
    }


void CSudokuBtnControl::HandlePointerEventL(const TPointerEvent& aPointerEvent)
    {
    if (aPointerEvent.iType == TPointerEvent::EButton1Up)
        {
        TInt number = Number(aPointerEvent.iPosition);
        if (number != KErrNotFound)
            {
            MakeVisible(EFalse);
            iDragPoint = iBtn5Rect.Center();
            iParent.GridControl()->NumberBtnPressed(number);
            }
        }
    else if (aPointerEvent.iType == TPointerEvent::EDrag || aPointerEvent.iType == TPointerEvent::EButton1Down)
        {
        iDragPoint = aPointerEvent.iPosition;
        }
    }

void CSudokuBtnControl::MakeVisible(TBool aVisible)
    {
    if (aVisible)
        {
        static_cast<CSudokuAppUi*>(iEikonEnv->EikAppUi())->UseSelectBackCbaL();
        }
    else
        {
        static_cast<CSudokuAppUi*>(iEikonEnv->EikAppUi())->UseOptionsExitCbaL();
        }
    CCoeControl::MakeVisible(aVisible);
    }
